﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Linq;

namespace PdfCompiler
{
    public partial class Form1 : Form
    {
        FileStream logFile;
        StreamWriter logger; 
        private string[] fileNames;
        private IOrderedEnumerable<IGrouping<string, FileInfo>> despachos;

        public Form1()
        {
            InitializeComponent();

            logFile = new FileStream("log.txt", FileMode.Create);
            logger = new StreamWriter(logFile);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            logger.Flush();
            logger.Close();
            Application.Exit();
        }

        private void btnExaminar_Click(object sender, EventArgs e)
        {
            DialogResult result = rootFolderBrowserDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                this.txtFolder.Text = rootFolderBrowserDialog.SelectedPath;

                BuscarArchivos();
            }
        }

        private void BuscarArchivos()
        {
            Log(String.Format("Buscado archivos en {0}...\n", rootFolderBrowserDialog.SelectedPath));
            fileNames = Directory.GetFiles(rootFolderBrowserDialog.SelectedPath, "*.pdf", SearchOption.AllDirectories);
            IEnumerable<FileInfo> files = fileNames.Select(f => new FileInfo(f));

            foreach (var file in files)
                Log(file + "\n");

            Log(String.Format("\nSe encontraron {0} archivos.\n", files.Count()));

            Log("\nDetectando despachos...\n");

            despachos = from f in files
                        where f.Name.Remove(f.Name.ToUpper().IndexOf(".PDF")).Length >= 16
                        group f by f.Name.ToUpper().Substring(0, 16) into fileGroup
                        orderby fileGroup.Key
                        select fileGroup;

            if (despachos.Count() == 0)
                Log("No se encontraron despachos.\n");
            else
            {
                Log("Se encontraron los siguientes despachos.\n");
                foreach (var despacho in despachos)
                {
                    Log(String.Format("{0}:\n", despacho.Key));

                    if (despacho.Count() > 1)
                    {
                        var directories = from f in despacho
                                      group f by f.DirectoryName into fileGroup
                                      orderby fileGroup.Key
                                      select fileGroup;

                        foreach (var directory in directories)
                        {
                            Log(String.Format("\tDirectorio: {0}\n", directory.Key));
                            
                            if (directory.Count() > 1)
                                foreach (var file in directory)
                                    Log(String.Format("\t\tArchivo parcial: {0}\n", file.Name));
                            else
                                Log(String.Format("\t\tArchivo único: {0} en {1}\n", directory.First().Name, directory.First().DirectoryName));
                        }
                    }
                    else
                        Log(String.Format("\tArchivo único: {0} en {1}\n", despacho.First().Name, despacho.First().DirectoryName));
                }
            }


        }

        private void btnCompile_Click(object sender, EventArgs e)
        {
            if (despachos == null || despachos.Count() == 0)
            {
                MessageBox.Show(
                    "No hay despachos para compilar.", 
                    "Error", 
                    MessageBoxButtons.OK, 
                    MessageBoxIcon.Exclamation);
            }

            Log("Compilando despachos...\n");
            foreach (var despacho in despachos)
            {
                Log(String.Format("> Despacho: {0}\n", despacho.Key));

                if (despacho.Count() > 1)
                {
                    var directories = from f in despacho
                                      group f by f.DirectoryName into fileGroup
                                      orderby fileGroup.Key
                                      select fileGroup;

                    foreach (var directory in directories)
                    {
                        Log(String.Format("\tDirectorio: {0}\n", directory.Key));

                        if (directory.Count() > 1)
                                CompilarArchivos(directory, despacho.Key);
                        else
                            Log(String.Format("\t\tArchivo único: {0} > No se procesará.\n", directory.First().Name));
                    }
                }
                else
                    Log(String.Format("\tArchivo único: {0} > No se procesará.\n", despacho.First().Name));
            }
        }

        private void CompilarArchivos(IGrouping<string, FileInfo> directory, string legajo)
        {
            try
            {
                Log(String.Format("\t\tCompilando archivos...\n"));
                string output = Path.Combine(directory.Key, legajo + ".PDF");
                if (File.Exists(output))
                {
                    Log(String.Format("\t\tEl archivo ya existe: {0}\n", output));
                }
                else
                {
                    string[] filepaths = directory.Select(d => d.FullName).ToArray();
                    PdfHelper.ConcatenatePdfFiles(filepaths, output);
                    Log(String.Format("\t\tCompilación exitosa. Se generó: {0}\n", output));
                }
            }
            catch (Exception ex)
            {
                Log(String.Format("\t\tERROR: {0}\n", ex.Message));
            }
        }

        private void Log(string message)
        {
            rtbStatus.AppendText(message);
            logger.WriteLine(DateTime.Now.ToLocalTime() + ": " + message);
        }
    }
}
